#
# man2html.pl
#
# Copyright 1996-2002, Silicon Graphics, Inc.
# All Rights Reserved.
#
# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
# the contents of this file may not be disclosed to third parties, copied or
# duplicated in any form, in whole or in part, without the prior written
# permission of Silicon Graphics, Inc.
#
# RESTRICTED RIGHTS LEGEND:
# Use, duplication or disclosure by the Government is subject to restrictions
# as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
# and Computer Software clause at DFARS 252.227-7013, and/or in similar or
# successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
# rights reserved under the Copyright Laws of the United States.
#
# requires perl5 and format2html.pl
#

require 'format2html.pl';


#######################################################################
#
# void man2html($root, $fname, $srch_str)
#
#######################################################################

sub man2html {

    my($manroot, $in_fname, $in_srch) = @_;

    if( $in_fname eq '' ) {
        print "man2html: filename not specified" if($_WEB == 0);
        return;
    }

    my($mancmd,$command,$section) = "";
    my($redirectpath)= "$manroot/usr/share/catman:" .
                       "$manroot/usr/share/man:$manroot/usr/catman:" .
                       "$manroot/usr/man";
    $ENV{'MANPATH'}=$redirectpath;

    &buildExpression($in_srch);

    my(@fname) = split(/\ /, $in_fname);
    if ($#fname == 0){

        if ($fname[0] =~ /\.gz$/){

            if($manroot && $fname[0] !~ /^$manroot/){
               &outputHTMLPage("$manroot/$fname[0]");
            }else{
               &outputHTMLPage($fname[0]);
            }
            return;

        }elsif($fname[0] =~ /\.(z|[1-9][a-zA-Z]*|Z)$/){

            # 3 cases:
            # 1) file is absolute /usr/share/catman/man1/test.z
            # 2) file is relative usr/share/catman/man1/test.z
            # 3) file is relative to the current location
            # 
            if($manroot){
               $mancmd = "/usr/bin/man -c -d $manroot/$fname[0] 2< /dev/null |";
            }else{
               $mancmd = "/usr/bin/man -c -d $fname[0] 2< /dev/null |";
            }
            &formatManPage($mancmd);
            return;

        }else{  
            # Find out how many man pages match
            #
            $command = $fname[0];
            $mancmd="/usr/bin/man -p $command 2< /dev/null |";
        }

    }elsif($#fname == 1 && $fname[0] =~ /[0-8]/){

        $section = $fname[0];
        $command = $fname[1];
        $mancmd="/usr/bin/man -p $section $command 2< /dev/null |";

    }else{
        print "man2html: incorrect filename specified" if($_WEB == 0);
        return;
    }


    my(@manpagefiles) = &findMatches($mancmd);

    # No man pages found, but an inaccurate cmd given?
    #
    if($#manpagefiles == -1 && $command =~ /__/){

       my($tmp_command) = $command;
       $tmp_command =~ s/__/_/g;
       $mancmd = "/usr/bin/man -p $section $tmp_command |";
       @manpagefiles = &findMatches($mancmd);
    }

    # One man page found; display it and get out
    #
    if ($#manpagefiles == 0){

        if ($manpagefiles[0] =~ /\.gz$/){
            &outputHTMLPage($manpagefiles[0]);
        }else{
            $mancmd = "/usr/bin/man -c -d $manpagefiles[0] 2< /dev/null |";
            &formatManPage($mancmd);
        }

        return;
    }

    # Multiple man pages
    #
    if ($#manpagefiles > 0){

        &HTMLHeaderFormat("Matching Man Pages");
        print '<B>Matching Man Pages</B>';
        &multiPageIndex($manroot,@manpagefiles);
        return;
    }

    # At this point, no man pages were found
    # Attempt fallback, use just cmd, not section id (if specified)
    #
    if ($section ne ''){

        $mancmd = "/usr/bin/man -p $command |";
        my(@manpagefiles) = &findMatches($mancmd);

        if ($#manpagefiles > -1) {
            &HTMLHeaderFormat("Matching Man Pages");
            print '<B>Alternate Matching Man Pages</B>',
                  '<p>Unable to find specific manual page for: ',
                  "<b>${command}(${section})</b>; found these as ",
                  "possible alternates:</p>\n";
            &multiPageIndex($manroot,@manpagefiles);
            return;
        }
    }

    &HTMLHeaderFormat("TPL");
    print "Unable to find a manual page for: $command";
    &HTMLTrailerFormat();
}


#######################################################################
#
# void formatManPage(String $mancmd)
#
# Uncompress the page and read it in one paragraph at a time.
# Pass in the man cmd, as opposed to just the file, because we can 
# tell if nroff exists on the system or not.
#
#######################################################################

sub formatManPage{

    my($mancmd) = @_;

    my($pgbrkcfmt) = "./pgbrkcfmt";
    my($ss2nonss)  = "./ss2nonss";
    my($manfilter) = "$pgbrkcfmt";
    my($manfile)   = $mancmd;

    if($manfile =~ /\ ([^\ ]+\.[^\ ]+)\ /){
	$manfile = $1;
	unless(-e $manfile){
	    die "$manfile: $!\n";
	}
    }else{
	die "Can't get filename: $mancmd\n";
    }
    
    if( $manfile =~ /\.z$/ ) {	                    # Packed
	$mancmd = "/usr/bin/pcat $manfile |col |";
    } elsif($manfile =~ /\.gz$/) {                  # Gzipped 
	$mancmd = "/usr/sbin/gzip -dc $manfile | $ss2nonss |";
    } elsif($manfile =~ /\.Z$/) {	            # Compressed
	$mancmd = "/usr/bsd/zcat $manfile |col |";
    } elsif($manfile =~ /(\.[1-8].*)$/) {           # Unformatted troff
        $mancmd = "/usr/bin/man -c -d $manfile | col -b |";
    } else {
	return;
    }
        
    open(MANINPUT, "$mancmd  $manfilter |") || die "$mancmd $manfilter: $!";

    $/ = "\n\n+";

    my @paraArray = ();

    local($refName) = "";
    local($refSection) = "";
    local($refTitle) = "";
    local($currentSectionName) = "";
    local($foundTitle)   = 0;
    local($foundHeader)  = 0;

    while(<MANINPUT>){

	if($_ eq ''){
	    next;
	}

        $_ =~ s/\+\x8//g;
	&pageBreakRemoval(\$_);

        if(/\n\n/){
            @paraArray = split(/\n\n+/, $_);
            foreach $para (@paraArray){
                &formatManParagraph(\$para);
                print "\n";
            }
        }else{
            &formatManParagraph(\$_);
        }
    }
    close(MANINPUT);

    &HTMLTrailerFormat();
    return;
}


#######################################################################
#
# void formatManParagraph(String_ref \$buf)
#
# Identify a paragraph
#
#######################################################################

sub formatManParagraph{

    my($buf_ref) = @_;
   
    if($$buf_ref eq ''){
	return;
    }

    # Remove trailing page numbers
    #
    if($$buf_ref =~ /(<B>)?Page(<\/B>)?\ (<B>)?\d\d?(<\/B>)?/){
        return;
    }

    if($foundHeader==0){	

	if ($$buf_ref =~ /^(\ *)(\S+)/){  # Get the name from the header
            # Missing a header - 1st para is NAME section
	    if($$buf_ref =~ /<B>NAME<\/B>\n\ +([^\ \,]+)/i){
		$refName = $1;
		$refSection="";
	    }else{
		($refName,$refSection) = &getHeaderInfo($2);
		$foundHeader=1;
		return;
	    }
	}else{
	    $foundHeader=0; 
	}
    }    

    if($foundTitle==0){		# Glean out the man page's title

	if($$buf_ref =~ /<B>NAME<\/B>\n\ +(.+)/i){ # Match Name or Name
	    $refTitle = &getTitle($$buf_ref,$refSection);
	    &HTMLHeaderFormat($refTitle);
	    &bigFormat($refName);
	    $foundTitle=1;
	}else{
	    $refTitle=$refName;
	    &HTMLHeaderFormat($refTitle);
	    &bigFormat($refName);
	    $foundTitle=1;
	}
    }
    
    #
    # At this point we have some sort of body paragraph
    # Apply links and keyword highlighting if necessary
    #
    &addLinks($buf_ref);
    &hilite($buf_ref);

    # this is for the named sections (NAME, SYNOPSIS, etc)
    #
    if($$buf_ref =~ /^<B>/) {
       $$buf_ref =~ s/^<B>/&nbsp;<B>/;
       $$buf_ref =~ s/\n/\n\n/;
    }

    print $$buf_ref, "\n";
}


#######################################################################
#
# @manpagefiles findMatches(String $mancmd)
#
# Build a list of man pages which match the command.
# For example, there my be multiple man pages named "test"
#
#######################################################################

sub findMatches{

    my($mancmd) = @_;
    my(@manpagefiles) = ();

    open(MANPIPE, $mancmd) || die "$mancmd: !$\n";

    while(<MANPIPE>){
	if(/^([^\/]+)(\/[\S]+)(\ *\|)(.+)/){
	   push(@manpagefiles, $2);
	}
    }
    close(MANPIPE);
    
    return(@manpagefiles);
}


#######################################################################
#
# ($refName,$refSection) = getHeaderInfo(String $buf);
#
#######################################################################

sub getHeaderInfo{

    my($refName) = @_;
    my($refSection) = "";

    &removeHTMLTags(\$refName);

    if($refName =~ /\((.+)\)/){
	$refSection = $1;
    }else{ # This could be a weird page like 2a_ctrl, which 
	   # has a header with a " " section: 2A_CTRL( )
	$refName =~ s/\(//;
    }

    return($refName,$refSection);
}


#######################################################################
#
# string getTitle(String $buf,String $refSection);
#
#######################################################################

sub getTitle{

    my($refTitle,$refSection) = @_;

    &removeHTMLTags(\$refTitle);
    $refTitle =~ s/NAME\n\ *//i;
    $refTitle =~ s/\n\ +/\ /g;
    $refTitle =~ s/\n//g;
    
    # Format the title in makewhatis format (add section number)
    if($refSection ne ""){
	$refTitle=~s/(\ +\-)/\ \($refSection\)$1/;
    }

    return($refTitle);
}


#######################################################################
#
# void multiPageIndex($manroot, Array @manpagefiles)
#
# When we have multiple man pages, create an index to a 
# list of pages. Print index to stdout.
#
#######################################################################

sub multiPageIndex{

    my($manroot) = shift @_;
    $manroot = quotemeta($manroot);

    my($script_name) = $ENV{SCRIPT_NAME} || "/cgi-bin/infosrch.cgi";
    my($coll) = "";
    $coll = (split(';', $COLLECTION))[0] if ($COLLECTION ne "");
    my($cgi) = "$script_name\?cmd=getdoc&coll=$coll&db=man&fname=";
    my($progType,$manPageName,$manPagePath,$useFileName) = "";

    my($bTable,$eTable) = "";
    my($i) = 0;

    $bTable = "\n<TABLE CELLPADDING=0>\n";
    $eTable = "</TABLE>\n";

    print $_ePreBody, $bTable;

    foreach $manPageFile (@_){

        $useFileName = $manPageFile;
        if ($manroot ne ''){
            $manPageFile =~ s/$manroot//;
            $useFileName = $manPageFile;
        }

        if($manPageFile =~ /(.+)\/(.+)\.z/o){

	    $manPagePath = $1;
	    $manPageName = $2; 

   	    print "<TR>\n";

	    $refType  = "Manual Reference Page";
	    $progType = '';
		
	    if ($manPagePath =~ /a_man/){
	        $refType = "Administrative Reference Page";
	    }elsif ($manPagePath =~ /g_man/){
	        $refType = "Graphics Reference Page";
	    }elsif ($manPagePath =~ /u_man/){
	        $refType = "Users' Reference Page";
	    }elsif ($manPagePath =~ /p_man/){
	    
	        if($manPagePath =~ /ftn/ || $manPagePath =~ /f90/){
		   $progType="Fortran ";
	        }elsif($manPagePath =~ /cat3c/ || $manPagePath =~ /standard/){
		   $progType="C ";
	        }elsif($manPagePath =~ /cat3dm/ || $manPagePath =~ /dmedia/){
		   $progType="Digital Media ";
	        }elsif($manPagePath =~ /cat3b/){
		   $progType="BSD ";
	        }elsif($manPagePath =~ /cat3n/){
		   $progType="Networking ";
	        }elsif($manPagePath =~ /catD/){
		   $progType="Device Driver ";
	        }elsif($manPagePath =~ /perl/){
		   $progType="Perl ";
	        }elsif($manPagePath =~ /\/X/){
		   $progType="X11,Xt,etc. ";
	        }
	    
	        $refType = "Programmers' Reference Page";
	    }
	
            $useFileName = &escape($useFileName);

            print "<TD><A HREF=\"${cgi}${useFileName}\">",
                  "${manPageName}</A></TD>\n<TD>",
                  "&nbsp;&nbsp;&nbsp;&nbsp;",
                  "${progType}${refType}</font></TD></TR>\n";
        }
    }
    print $eTable, $_bPreBody;
    &HTMLTrailerFormat();
}


# Return true from package include
#
1;

